package com.a0soft.gphone.aTruffleHog.di;
/*
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 3, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * Copyright(C) 2011 
 *   Sam Lu <ysl.sam.lu (at) gmail.com>
 *
 */

import java.lang.reflect.Method;

import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Point;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;

import com.a0soft.gphone.aTruffleHog.util.CONSTS;
import com.a0soft.gphone.aTruffleHog.util.MiscUtil;
import com.a0soft.gphone.aTruffleHog.util.SDK13;
import com.a0soft.gphone.aTruffleHog.util.aDebug;

class DisplayInfo extends BaseInfo {    
    private static final String LOG_TAG = DisplayInfo.class.getSimpleName();
    
    static void
    Build(DeviceInfo di)
    {
        Context ctx = MiscUtil.GetAppContext();
        
        WindowManager mgrWnd = (WindowManager)ctx.getSystemService(Context.WINDOW_SERVICE);
        Display dp = mgrWnd.getDefaultDisplay();
        DisplayMetrics dm = ctx.getResources().getDisplayMetrics();//new DisplayMetrics();
        dp.getMetrics(dm);
        
        int nOri = dp.getOrientation();
        
        Point pt = _GetPhysicalScreenSize(dp, dm);        
        int nPhyScrW = pt.x;
        int nPhyScrH = pt.y;
        if (nOri == Surface.ROTATION_270 || 
            nOri == Surface.ROTATION_90) {
            int nTemp = nPhyScrW;
            nPhyScrW = nPhyScrH;
            nPhyScrH = nTemp;
        }
        
    	di.Put(DeviceInfoKey.K.DP_W, nPhyScrW);
        di.Put(DeviceInfoKey.K.DP_H, nPhyScrH);
        di.Put(DeviceInfoKey.K.DP_DENSITY, dm.density);
        di.Put(DeviceInfoKey.K.DP_SDENSITY, dm.scaledDensity);
        di.Put(DeviceInfoKey.K.DP_DDPI, dm.densityDpi);
        //xdpi, ydpi won't be swapped according to orientation, so we don't swap it
        di.Put(DeviceInfoKey.K.DP_XDPI, dm.xdpi); 
        di.Put(DeviceInfoKey.K.DP_YDPI, dm.ydpi);
        di.Put(DeviceInfoKey.K.DP_PIXEL_FMT, dp.getPixelFormat());
        di.Put(DeviceInfoKey.K.DP_REFRESH_RATE, dp.getRefreshRate());
        
        float fPhyScrSizeW = nPhyScrW / dm.xdpi;
        float fPhyScrSizeH = nPhyScrH / dm.ydpi;
        float fScreen = ((int)(Math.sqrt(fPhyScrSizeW * fPhyScrSizeW + fPhyScrSizeH * fPhyScrSizeH) * 10 + 0.5)) / 10f;
        di.Put(DeviceInfoKey.K.DP_SCREEN_SIZE, fScreen);
        
        Configuration cfg = Resources.getSystem().getConfiguration();
        di.Put(DeviceInfoKey.K.DP_FONT_SCALE, cfg.fontScale);
        int nLayoutSize = cfg.screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK;
        di.Put(DeviceInfoKey.K.DP_LAYOUT_SIZE, nLayoutSize);
        int nLayoutAspect = cfg.screenLayout & Configuration.SCREENLAYOUT_LONG_MASK;
        di.Put(DeviceInfoKey.K.DP_LAYOUT_ASPECT, nLayoutAspect);

        if (MiscUtil.GetSDKVersion() >= 13) {
            SDK13 sdk13 = SDK13.GetInstance();
            di.Put(DeviceInfoKey.K.DP_LAYOUT_SWIDTH, sdk13.Configuration_smallestScreenWidthDp(cfg));
            
            int nW = sdk13.Configuration_screenWidthDp(cfg);
            int nH = sdk13.Configuration_screenHeightDp(cfg);
            if (nOri == Surface.ROTATION_270 || 
                nOri == Surface.ROTATION_90) {
                int nTemp = nW;
                nW = nH;
                nH = nTemp;

                int nStatusBar = (nW != nPhyScrW) ? (nPhyScrW - nW) : 0;
                if (nStatusBar > 0) {
                    nW += nStatusBar;
                    nH -= nStatusBar;
                }
            }
            
            di.Put(DeviceInfoKey.K.DP_LAYOUT_AWIDTH, nW);
            di.Put(DeviceInfoKey.K.DP_LAYOUT_AHEIGHT, nH);
        }
        else {
            di.Put(DeviceInfoKey.K.DP_LAYOUT_SWIDTH, CONSTS.UNAVAILABLE);
            di.Put(DeviceInfoKey.K.DP_LAYOUT_AWIDTH, CONSTS.UNAVAILABLE);
            di.Put(DeviceInfoKey.K.DP_LAYOUT_AHEIGHT, CONSTS.UNAVAILABLE);
        }
        
        if (aDebug.ENABLED) {
            aDebug.d(LOG_TAG, "mcc=" + cfg.mcc);
            aDebug.d(LOG_TAG, "mnc=" +  cfg.mnc);
            
            String str;
            str = "" + nLayoutSize;
            switch (nLayoutSize) {
            case Configuration.SCREENLAYOUT_SIZE_SMALL: str += "(small)"; break;
            case Configuration.SCREENLAYOUT_SIZE_NORMAL: str += "(normal)"; break;
            case Configuration.SCREENLAYOUT_SIZE_LARGE: str += "(large)"; break;
            case Configuration.SCREENLAYOUT_SIZE_XLARGE: str += "(xlarge)"; break;
            case Configuration.SCREENLAYOUT_SIZE_UNDEFINED: str += "(undefined)"; break;
            }
            aDebug.d(LOG_TAG, "layout sized=" + str);
            
            str = "" + nLayoutAspect;
            switch (nLayoutAspect) {
            case Configuration.SCREENLAYOUT_LONG_YES: str += "(long)"; break;
            case Configuration.SCREENLAYOUT_LONG_NO: str += "(notlong)"; break;
            case Configuration.SCREENLAYOUT_LONG_UNDEFINED: str += "(undefined)"; break;
            }
            aDebug.d(LOG_TAG, "layout aspect=" + str);
        }
    }	
    
    private static Point
    _GetPhysicalScreenSize(Display dp, DisplayMetrics dm)
    {
        if (aDebug.ENABLED) {
            aDebug.d(LOG_TAG, "dp.getWidth()=" + dp.getWidth());
            aDebug.d(LOG_TAG, "dp.getHeight()=" + dp.getHeight());
            /*Method[] methods;
            methods = Display.class.getMethods();
            for (Method m: methods) {
                aDebug.d(LOG_TAG, "method" + m.getName());
            }*/
        }
        
        Method mGetRawH = null;
        Method mGetRawW = null;
        try {
            //on 3.2 or above, status bar height is not included in DisplayMetrics's height
            //we have to use undocumented APIs to get physical w/h
            mGetRawW = Display.class.getMethod("getRawWidth");
            mGetRawH = Display.class.getMethod("getRawHeight");
            if (mGetRawH != null && mGetRawW != null) {
                int nW = (Integer)mGetRawW.invoke(dp);
                int nH = (Integer)mGetRawH.invoke(dp);
                if (aDebug.ENABLED) {
                    aDebug.d(LOG_TAG, "getRawWidth()=" + nW);
                    aDebug.d(LOG_TAG, "getRawHeight()=" + nH);
                }
                return new Point(nW, nH);
            }
        }
        catch (Exception e) {
        }
             
        return new Point(dm.widthPixels, dm.heightPixels);
    }
}
